import "../css/style.css";
import "../css/desert.css";
import "../css/smoothness/jquery-ui-1.8.13.custom.css";

let gl = null;      // WebGL 上下文
let prg = null;     // program 着色器
let c_width = 0;    // canvas的宽
let c_height = 0;   // canvas的高

let trapezoidVertexBuffer = null;  // 正方形顶点缓冲区
let trapezoidIndexBuffer = null;   // 正方形索引缓冲区

let indices = [];   // 存储正方形索引的数组
let vertices = [];  // 存储正方形顶点的数组

let renderingMode = 'TRIANGLES';

/**
 * 一些操作图形处理器(GPU)的指令
 * 如何处理我们传入的顶点和片元（有关详细信息，请参阅第3章）
 */
function initProgram() {
    let fgShader = utils.getShader(gl, 'shader-fs');
    let vxShader = utils.getShader(gl, 'shader-vs');

    prg = gl.createProgram();
    // 添加一个预先定义的着色器
    gl.attachShader(prg, vxShader);
    gl.attachShader(prg, fgShader);
    gl.linkProgram(prg);

    if (!gl.getProgramParameter(prg, gl.LINK_STATUS)) {
        alert('Could not initialise shaders');
    }

    gl.useProgram(prg);
    //下面代码获取着色器中的uniforms和attributes的引用
    // 这是一个必须的步骤，因为着色器不是用JavaScript编写的，而是用GLSL语言。
    prg.vertexPosition = gl.getAttribLocation(prg, 'aVertexPosition');
}

/*
    * Creates the buffers that contain the geometry of the square
    *

    */

/**
 *  创建梯形缓冲区
 *
 *      #1 (-0.25,0.5)  +--------------+  (0.25,0.5)  #3
 *                     /                \
 *                    /                  \
 *                   /          .(0,0)    \
 *                  /                      \
 *                 /                        \
 * #0(-0.5,-0.5)  +------------+-------------+  (0.5,-0.5) #4
 *                             #2(0,-0.5)
 */
function initBuffers() {

    vertices = [
        -0.5, -0.5, 0.0,     // Vertex 0
        -0.25, 0.5, 0.0,    // Vertex 1
        0.0, -0.5, 0,       // Vertex 2
        0.25, 0.5, 0.0,     // Vertex 3
        0.5, -0.5, 0.0      // Vertex 4
    ];

    indices = [0, 1, 2, 0, 2, 3, 2, 3, 4];  // 四个三角形

    // 顶点缓冲区
    trapezoidVertexBuffer = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, trapezoidVertexBuffer);
    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
    gl.bindBuffer(gl.ARRAY_BUFFER, null);

    // 索引缓冲区
    trapezoidIndexBuffer = gl.createBuffer();
    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, trapezoidIndexBuffer);
    gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), gl.STATIC_DRAW);
    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
}

function drawScene() {
    gl.clearColor(0.0, 0.0, 0.0, 1.0);
    gl.enable(gl.DEPTH_TEST);

    gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
    gl.viewport(0, 0, c_width, c_height);

    gl.bindBuffer(gl.ARRAY_BUFFER, trapezoidVertexBuffer);
    gl.vertexAttribPointer(prg.aVertexPosition, 3, gl.FLOAT, false, 0, 0);
    gl.enableVertexAttribArray(prg.vertexPosition);

    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, trapezoidIndexBuffer);
    switch (renderingMode) {
        case 'TRIANGLES': {
            indices = [0, 1, 2, 2, 3, 4];
            gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), gl.STATIC_DRAW);
            gl.drawElements(gl.TRIANGLES, indices.length, gl.UNSIGNED_SHORT, 0);
            break;
        }
        case 'LINES': {
            indices = [1, 3, 0, 4, 1, 2, 2, 3];
            gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), gl.STATIC_DRAW);
            gl.drawElements(gl.LINES, indices.length, gl.UNSIGNED_SHORT, 0);
            break;
        }
        case 'POINTS': {
            indices = [1, 2, 3];
            gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), gl.STATIC_DRAW);
            gl.drawElements(gl.POINTS, indices.length, gl.UNSIGNED_SHORT, 0);
            break;
        }
        case 'LINE_LOOP': {
            indices = [2, 3, 4, 1, 0];
            gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), gl.STATIC_DRAW);
            gl.drawElements(gl.LINE_LOOP, indices.length, gl.UNSIGNED_SHORT, 0);
            break;
        }
        case 'LINE_STRIP': {
            indices = [2, 3, 4, 1, 0];
            gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), gl.STATIC_DRAW);
            gl.drawElements(gl.LINE_STRIP, indices.length, gl.UNSIGNED_SHORT, 0);
            break;
        }
        case 'TRIANGLE_STRIP': {
            indices = [0, 1, 2, 3, 4];
            gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), gl.STATIC_DRAW);
            gl.drawElements(gl.TRIANGLE_STRIP, indices.length, gl.UNSIGNED_SHORT, 0);
            break;
        }
        case 'TRIANGLE_FAN': {
            indices = [0, 1, 2, 3, 4];
            gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), gl.STATIC_DRAW);
            gl.drawElements(gl.TRIANGLE_FAN, indices.length, gl.UNSIGNED_SHORT, 0);
            break;
        }
    }
}

function renderLoop() {
    utils.requestAnimFrame(renderLoop);
    drawScene();
}

let changeBtn = document.getElementById('option-select');
changeBtn.addEventListener('change', evt => {
    renderingMode = evt.currentTarget[evt.currentTarget.selectedIndex].value;
});

function runWebGLApp() {
    // console.log(utils);
    gl = utils.getGLContext('canvas-element-id');
    c_width = gl.canvas.width;
    c_height = gl.canvas.height;

    initProgram();

    initBuffers();

    renderLoop();
}

runWebGLApp();
